fix(typing): Narrow TypeVar(s) used in (Data|Lazy)Frame#2356
fix(typing): Narrow TypeVar(s) used in (Data|Lazy)Frame#2356MarcoGorelli merged 33 commits intomainfrom
TypeVar(s) used in (Data|Lazy)Frame#2356Conversation
Revealed quite a few other issues
+ fix related quirks
- I think this whole test needs rewriting - We shouldn't be depending on the internals like this
Spent waaaaaay too long trying to get this working
tests/translate/from_native_test.py
Outdated
| def test_dataframe_recursive_v1() -> None: | ||
| pytest.importorskip("polars") | ||
| import polars as pl | ||
|
|
||
| pl_frame = pl.DataFrame({"a": [1, 2, 3]}) | ||
| nw_frame = nw.from_native(pl_frame) | ||
| with pytest.raises(AssertionError): | ||
| nw.DataFrame(nw_frame, level="full") | ||
|
|
||
| nw_frame_early_return = nw.from_native(nw_frame) | ||
|
|
||
| if TYPE_CHECKING: | ||
| assert_type(pl_frame, pl.DataFrame) | ||
| # TODO @dangotbanned: Fix without breaking something else (1) | ||
| assert_type(nw_frame, nw.DataFrame[pl.DataFrame]) | ||
|
|
||
| nw_frame_depth_2 = nw.DataFrame(nw_frame, level="full") | ||
| # NOTE: Checking that the type is `DataFrame[Unknown]` | ||
| assert_type(nw_frame_depth_2, nw.DataFrame) | ||
| # TODO @dangotbanned: Fix without breaking something else (2) | ||
| assert_type(nw_frame_early_return, nw.DataFrame[pl.DataFrame]) |
There was a problem hiding this comment.
- Spent a few hours trying to get this working
- Nothing I've tried worked for both
mypy,pyrightand didn't break something elsewhere
There was a problem hiding this comment.
AFAICT, v1s overloads were always returning a Union for the case I was trying to force into DataFrame.
Gave up on trying to resolve in (c4bed59)
| @@ -1,5 +1,6 @@ | |||
| from __future__ import annotations | |||
|
|
|||
| # mypy: disallow-any-generics=false, disable-error-code="var-annotated" | |||
There was a problem hiding this comment.
Needed to add this to avoid mypy requiring # type: ignores.
If a line has one (regardless of it is has an error code) pyright won't ever emit a diagnostic
There was a problem hiding this comment.
Moved into a docstring for a better explainer (6a66779)
There was a problem hiding this comment.
@FBruzzesi in relation to (#2304 (comment))
I think there's quite a lot of things to be learned - by following this PR all the way back to the original issue (#2239) 🙂
There was a problem hiding this comment.
Thanks for the ping! I just went through the entire PR, my skill issue is that everything makes sense, but most likely I would not be able to (re)produce it 🥲
There was a problem hiding this comment.
@FBruzzesi so if you go through the PR (or (https://github.com/narwhals-dev/narwhals/pull/2347/commits)) in order of commits - there's a pattern in all of this.
Is this a workflow?
- Identify some typing that doesn't meet your expectation ([Bug]:
TypeVar(s) used innw.(BaseFrame|Series)are recursive #2239) - Make the smallest change you think could fix it (74a03a8)
- Write a test that would demonstrate the bug was fixed (ff841d1)
- I probably should've started with that, but I was eager I guess 😉
- Add some notes when that didn't work (ff841d1#r2029276670)
- Add even more notes when all seems lost (37549cc)
- Try absolutely anything to fix it (6bd47b4)
- I wasn't happy with this initially, but became more convinced when it didn't break anything else
- Without the tests in place - I might have not even tried this
- Write an essay on why you think that worked (6bd47b4#r2029455047)
- Clean things up (50e4d13)
Back to this PR
You can follow through (aa6578e) and Next > to see a similar thing 🙂
Different issues came up, but I'm mostly trying to isolate small things and see what mypy & pyright spits back out when I attempt a fix
There was a problem hiding this comment.
I also usually try to get the typing right first before I start making "real" code changes.
It is much harder to spot the source of an issue if you only check the types after making lots of changes
MarcoGorelli
left a comment
There was a problem hiding this comment.
thanks @dangotbanned ! just got a question
narwhals/_polars/dataframe.py
Outdated
| index: list[str] | None, | ||
| values: list[str] | None, | ||
| index: str | Sequence[str] | None, | ||
| values: str | Sequence[str] | None, |
There was a problem hiding this comment.
why do these change? is Sequence[str] | None not fine?
There was a problem hiding this comment.
thanks @dangotbanned ! just got a question
Thanks @MarcoGorelli, happy to answer 😅
why do these change? is
Sequence[str] | Nonenot fine?
the original annotation was overly narrow, since polars accepts much more than a list
- https://docs.pola.rs/api/python/stable/reference/dataframe/api/polars.DataFrame.pivot.html
- https://github.com/pola-rs/polars/blob/py-1.26.0/py-polars/polars/dataframe/frame.py#L8732-L8963
I followed through to pandas to see if that was the source of using list[str], but IIRC it used an alias like IndexLabel.
Sequence[str] | None is equivalent to str | Sequence[str] | None sadly (python/typing#256).
But I prefer being more explicit that it can accept "one or more columns"
There was a problem hiding this comment.
if it's str we already make it a list at the narwhals level, can this just be Sequence[str] | None?
|
@MarcoGorelli I've resolved the conflicts from #2380 Are we good to go on this one? |
| class DataFrameGroupBy( | ||
| CompliantGroupBy[CompliantDataFrameT_co, CompliantExprT_contra], | ||
| Protocol38[CompliantDataFrameT_co, CompliantExprT_contra], | ||
| ): | ||
| def __iter__(self) -> Iterator[tuple[Any, CompliantDataFrameT_co]]: ... |
There was a problem hiding this comment.
@FBruzzesi I forgot to mention this will probably be helpful in getting the typing working for (#2325).
It means you can use CompliantGroupBy for Polars* and put the unrelated parts here.
I needed to add it to resolve an unrelated issue (1815752)
No worries @MarcoGorelli! I'm just happy we're now in a good place to work on 😊 |


Will close #2344, #2345
What type of PR is this? (check all applicable)
Related issues
TypeVarused inDataFrame#2344TypeVarused inLazyFrame#2345pivotto Arrow #2179Checklist
If you have comments or can explain your changes, please do so below
mainTypeAliass and@overloadsDataFrame._compliant_frameLazyFrame._compliant_framev1LazyFrameoverloadDataFrameoverload